package com.allwees.core.wf;

import org.apache.commons.collections.CollectionUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 简单工作流状态节点实现 - 有限状态机（FSM）版本
 *
 * @author yangylsky
 */
public interface FsmState<S extends FsmState<S, A>, A extends Action> extends Serializable {
	/**
	 * 当前状态的唯一名称
	 *
	 * @return
	 */
	String name();

	/**
	 * 是否是进行中状态的节点
	 *
	 * @return
	 */
	boolean started();

	/**
	 * 是否是结束状态的节点（已经结束的流程不能再变迁）
	 *
	 * @return
	 */
	boolean ended();

	/**
	 * 当前状态的上一个状态
	 *
	 * @return
	 */
	default S lastState() {
		return null;
	}

	/**
	 * 是否是起点状态的节点
	 *
	 * @return
	 */
	default boolean isStartable() {
		return !started() && !ended();
	}

	/**
	 * 无条件变迁到下一个对应的状态节点。注：当前状态节点的状态变迁定义必须支持无条件变迁
	 *
	 * @return
	 */
	default S transit() {
		return transit(null);
	}

	/**
	 * 根据参数变迁到下一个对应的状态节点
	 *
	 * @param action
	 * @return
	 */
	default S transit(A action) {
		if(ended()) {
			throw new WfStateException("当前状态为已经结束，无法执行变迁操作");
		}
		List<Transition<S, A>> transitions = getTransitions();
		if(CollectionUtils.isEmpty(transitions)) {
			throw new WfStateException("当前状态变迁定义为空，无法执行变迁操作");
		}
		if(action == null) {
			if(transitions.get(0).getAction() == null) { //无条件变迁必须在第一个元素
				return transitions.get(0).getState();
			} else {
				throw new IllegalArgumentException("当前状态变迁定义不支持无条件变迁");
			}
		}
		for(Transition<S, A> transition : transitions) {
			if(action.equals(transition.getAction())) {
				return transition.isBack() ? lastState() : transition.getState();
			}
		}
		throw new WfStateException("当前状态找不到对应Action[" + action + "]的变迁定义，请检查传入参数和变迁定义");
	}

	/**
	 * 当前状态的迁出定义
	 *
	 * @return
	 */
	default List<Transition<S, A>> getTransitions() {
		return new ArrayList<>();
	}
}
